

#include "Stack.h"
#include <cmath>
#include <string>
#include "Assembler.h"

using std::string;

class CPU
{
    private:
        Stack<double> stack_;
        double x_;

    public:
        void mul();
        void div();
        void sub();
        void add();
        void sqrt_();
        void sin_();
        void cos_();

        void set_x(double x) { x_ = x; }

        double run();

        void   push(double val) { stack_.push(val);    }
        double pop()            { return stack_.pop(); }

        void print() { cout << stack_.last(); }
};

void CPU::mul()
{
    push(pop() * pop());
}

void CPU::div()
{
    int b = pop();
    int a = pop();

    push(a/b);
}

void CPU::add()
{
    push(pop() + pop());
}

void CPU::sub()
{
    int b = pop();
    int a = pop();

    push(a - b);
}

void CPU::sqrt_() { push(sqrt(pop())); }
void CPU::sin_()  { push(sin(pop())); }
void CPU::cos_()  { push(cos(pop())); }

double CPU::run()
{
    int cmd = 0;

    cin >> cmd;

    while(cmd != END.code)
    {
        if(cmd == PUSH.code)
        {
            float val = 0;
            cin >> val;
            push(val);
        }

        if(cmd == ADD.code)   add();
        if(cmd == MUL.code)   mul();
        if(cmd == DIV.code)   div();
        if(cmd == SUB.code)   sub();
        if(cmd == SIN.code)   sin_();
        if(cmd == COS.code)   cos_();
        if(cmd == SQRT.code)  sqrt_();
        if(cmd == PUSHX.code) push(x_);

        cin >> cmd;
    }
    try { return stack_.last(); }
    catch(const char* exc)
    {
        $r cout << exc; $d
    }
}
